package org.gpp.proj1.logic;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.gpp.proj1.communication.CommunicationException;
import org.gpp.proj1.communication.ConnectionException;
import org.gpp.proj1.communication.listener.ConnectionAttemptListener;
import org.gpp.proj1.logic.core.server.ServerPhaseException;
import org.gpp.proj1.logic.metadata.PartCategory;
import org.gpp.proj1.logic.metadata.PartEntry;
import org.gpp.proj1.logic.metadata.RobotEntry;
import org.gpp.proj1.logic.metadata.RobotPartCategory;
import org.gpp.proj1.logic.profile.PlayerProfile;
import org.gpp.proj1.logic.profile.UnsufficientFundsException;
import org.gpp.proj1.ui.controller.ISRGUIController;

/**
 * SomeRobotGame MVC Model interface 
 * 
 * @author Paolo Victor, paolovictor@gmail.com
 */
public interface ISRGUIModel {
	public Set<String> getPlayerProfileNames();
	
	public void createPlayerProfile( String playerName );
	
	public void setController( ISRGUIController controller );

	public void start();

	public void notifyProfileNotLoaded();

	public void loadProfile(String playerName);

	/**
	 * @return The currently loaded profile name, or <code>null</code>
	 * if there are no loaded profile
	 */
	public PlayerProfile getCurrentProfile();

	/**
	 * Loads and returns the complete parts list
	 * 
	 * @return A map with the parts, separated by category (Category->PartMap)
	 */
	public Map<PartCategory, Map<String, PartEntry>> getPartsList();

	/**
	 * Buys a part from the part shop
	 * 
	 * @param category
	 * @param part
	 * @param quantity
	 * @throws UnsufficientFundsException 
	 */
	public void buyPart(PartCategory category, String part, int quantity) throws UnsufficientFundsException;

	/**
	 * @param category
	 * @return The available parts for the given category
	 */
	public Map<PartEntry, Integer> getAvailableParts(PartCategory category);

	/**
	 * Saves a robot to the player profile
	 * @param oldRobot The old robot's name
	 * @param newRobot The new robot's name
	 * @param parts The robot part map
	 */
	public void saveRobot(String oldRobot, String newRobot, Map<RobotPartCategory, PartEntry> parts);

	/**
	 * @return A list with the player's robot entries
	 */
	public List<RobotEntry> getPlayerRobots();

	/**
	 * @param robot
	 * @return A string with the robot's description, from its RobotEntry
	 */
	public String getRobotDescription(String robot);

	/**
	 * Deletes a robot from the player profile
	 * @param robotName
	 */
	public void deleteRobot(String robotName);


	/**
	 * Starts a server with the given parameters 
	 * @param name
	 * @param maxPlayers
	 * @param string
	 * @param mapName
	 * @param port
	 * @throws ConnectionException 
	 * @throws CommunicationException 
	 */
	public void startServer(String name, int maxPlayers, String mapName, File mapFile, int port) throws CommunicationException;

	/**
	 * @return If the game client is connected to a server
	 */
	public boolean isClientConnected();

	/**
	 * Closes the connection to the game server and stops server
	 * @throws CommunicationException 
	 */
	public void closeConnection() throws CommunicationException;

	/**
	 * Connects to a server
	 * 
	 * @param listener The listener entity for connection events
	 * @param address The server address, on the x.x.x.x:port format
	 * @param localPort The local request processor port
	 * @throws CommunicationException 
	 */
	public void connectToServer(ConnectionAttemptListener listener, String address, int localPort) throws CommunicationException;
	
	/**
	 * Sends a chat message
	 * @param text The message
	 * @throws CommunicationException 
	 */
	public void sendChatMessage(String text) throws CommunicationException;

	/**
	 * Changes the game map. Available only for the game server
	 * @param selectedValue
	 * @throws CommunicationException If the client isn't connected or isn't a server
	 */
	public void changeGameMap(String mapName) throws CommunicationException;

	/**
	 * @return <code>true</code> if the client is a game server 
	 */
	public boolean isServer();

	/**
	 * Notifies the server to change the client's readiness state
	 * @throws CommunicationException 
	 */
	public void toggleReadinessState() throws CommunicationException;

	/**
	 * @return <code><code>true</code> if the client is a server and may start a game (has enough
	 * players on ready state)
	 */
	public boolean mayStartGame();

	/**
	 * Disconnects the game client and server
	 * @throws CommunicationException 
	 */
	public void disconnect() throws CommunicationException;

	/**
	 * Kicks the player with the parameter id from the server
	 * @param clientId
	 * @throws CommunicationException 
	 */
	public void kickPlayer(String clientId) throws CommunicationException;

	/**
	 * Notifies the interface that the server initialization phase
	 * has failed
	 * 
	 * @param cause The fail cause
	 */
	public void initGame() throws CommunicationException, ServerPhaseException;

	public void notifyReadyToStartGame() throws CommunicationException;

	public String getCurrentPlayerId() throws CommunicationException;

	public void endTurn() throws CommunicationException;

	public void movedRobot(String robot, int newX, int newY) throws CommunicationException;

	public void robotAttacked(String robot, int selectedX, int selectedY, String selectedPart, String selectedAttack) throws CommunicationException;
}
